fix: scaffold .chronicle/ directory for Turbopack compatibility#21
fix: scaffold .chronicle/ directory for Turbopack compatibility#21
Conversation
…path When installed via npx/bunx or as a dependency, next gets hoisted and node_modules/.bin/next doesn't exist inside the chronicle package dir. Use createRequire + require.resolve to find next/dist/bin/next via Node's module resolution which handles hoisting automatically. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows placing chronicle.yaml in project root when using chronicle as a library dependency, while still supporting it inside content dir. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughReplaces content-dir driven flows with a scaffold-first workflow: CLI commands now require a local Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as Chronicle CLI
participant FS as Filesystem
participant PM as PackageManager
participant NodeExec as Node (process.execPath)
participant NextCLI as Next CLI (resolved)
User->>CLI: run init / dev / build / start
CLI->>FS: check for `.chronicle` (scaffold)
alt scaffold missing and command is init
CLI->>FS: create project files (package.json, chronicle.yaml, content/index.mdx, .gitignore)
else scaffold missing for dev/build/start
CLI-->>User: error ("scaffold not found")
end
CLI->>CLI: scaffoldDir -> copy templates into `.chronicle`
CLI->>PM: detectPackageManager -> install dependencies
PM-->>CLI: install complete
CLI->>FS: ensure `.chronicle/content` -> symlink to `./content`
CLI->>NodeExec: spawn process with resolved Next CLI path
NodeExec->>NextCLI: execute (dev/build/start) in cwd = `.chronicle`
NextCLI->>FS: read `.chronicle` config & content
NextCLI-->>User: serve or build output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip You can customize the tone of the review comments and chat replies.Configure the |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/chronicle/src/cli/utils/config.ts (1)
19-25: Code duplication withlib/config.ts.This
resolveConfigPathimplementation duplicates the logic inpackages/chronicle/src/lib/config.ts:14-23, with slight semantic differences: the CLI version takescontentDiras a parameter while the lib version reads fromprocess.env.CHRONICLE_CONTENT_DIRdirectly. Consider extracting a shared utility to avoid drift between these two implementations.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/chronicle/src/cli/utils/config.ts` around lines 19 - 25, The resolveConfigPath implementation in CLI (resolveConfigPath) duplicates logic from lib/config.ts; extract a shared utility (e.g., findChronicleConfig) into a common module that accepts an optional contentDir parameter (and falls back to process.env.CHRONICLE_CONTENT_DIR when undefined) and replace both resolveConfigPath and the code in packages/chronicle/src/lib/config.ts to call this shared function so behavior is centralized and avoids drift.packages/chronicle/src/cli/commands/dev.ts (1)
5-11: Consider extracting shared Next.js CLI resolution.The
createRequire+require.resolve('next/dist/bin/next')pattern is duplicated acrossdev.ts,build.ts,start.ts, andserve.ts. Consider extracting this to a shared utility (e.g., in@/cli/utils) to reduce duplication and centralize the resolution logic.♻️ Example shared utility
// In `@/cli/utils/next.ts` import { createRequire } from 'module' const require = createRequire(import.meta.url) export const nextCli = require.resolve('next/dist/bin/next')🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/chronicle/src/cli/commands/dev.ts` around lines 5 - 11, The Next.js CLI resolution (createRequire + require.resolve('next/dist/bin/next')) is duplicated in dev.ts (and also in build.ts, start.ts, serve.ts); extract it into a shared utility (e.g., add a new export nextCli in "@/cli/utils/next" or "@/cli/utils") that performs createRequire(import.meta.url) and resolves 'next/dist/bin/next', then import and use that exported nextCli symbol in dev.ts, build.ts, start.ts and serve.ts to remove duplication and centralize resolution logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/chronicle/src/cli/utils/config.ts`:
- Around line 30-31: The error message built when the configPath check fails
currently uses comma-separated console.log arguments which yields awkward
spacing; update the code inside the configPath falsy branch (the if
(!configPath) block) to build a single formatted string — e.g., use a template
literal combining process.cwd() and contentDir — and pass that single string
into chalk.red so the entire message is colored and properly formatted (for
example: console.log(chalk.red(`Error: chronicle.yaml not found in
${process.cwd()} or ${contentDir}`))).
---
Nitpick comments:
In `@packages/chronicle/src/cli/commands/dev.ts`:
- Around line 5-11: The Next.js CLI resolution (createRequire +
require.resolve('next/dist/bin/next')) is duplicated in dev.ts (and also in
build.ts, start.ts, serve.ts); extract it into a shared utility (e.g., add a new
export nextCli in "@/cli/utils/next" or "@/cli/utils") that performs
createRequire(import.meta.url) and resolves 'next/dist/bin/next', then import
and use that exported nextCli symbol in dev.ts, build.ts, start.ts and serve.ts
to remove duplication and centralize resolution logic.
In `@packages/chronicle/src/cli/utils/config.ts`:
- Around line 19-25: The resolveConfigPath implementation in CLI
(resolveConfigPath) duplicates logic from lib/config.ts; extract a shared
utility (e.g., findChronicleConfig) into a common module that accepts an
optional contentDir parameter (and falls back to
process.env.CHRONICLE_CONTENT_DIR when undefined) and replace both
resolveConfigPath and the code in packages/chronicle/src/lib/config.ts to call
this shared function so behavior is centralized and avoids drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 69d15e4f-0518-4c4a-9966-8782bed0715d
📒 Files selected for processing (7)
packages/chronicle/bin/chronicle.jspackages/chronicle/src/cli/commands/build.tspackages/chronicle/src/cli/commands/dev.tspackages/chronicle/src/cli/commands/serve.tspackages/chronicle/src/cli/commands/start.tspackages/chronicle/src/cli/utils/config.tspackages/chronicle/src/lib/config.ts
Publishes canary npm release on every PR commit with version format 0.1.0-canary.<short-sha> using --tag canary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/canary.yml:
- Around line 3-5: The workflow is triggered on pull_request which exposes repo
secrets only for same-repo PRs, so guard the publish path: modify the publish
job or the specific publish step to run only for same-repo PRs by adding an if
condition that compares the PR head repo to the base/repository (e.g. if:
github.event.pull_request.head.repo.full_name ==
github.event.pull_request.base.repo.full_name) or gate the whole job similarly;
alternatively, keep pull_request but change only the publish step/job to use
that same-repo conditional so forked PRs won’t attempt publishing.
- Around line 29-38: The current canary flow uses SHORT_SHA and sets VERSION
then always runs bun publish, which will fail on reruns for the same commit;
modify the job so that before running bun publish it checks the registry for the
computed VERSION (e.g., with npm view <package>@$VERSION or npm info
<package>@$VERSION) and if that version already exists skip the publish step
(echo/skipped) instead of attempting bun publish, keeping the existing VERSION
and SHORT_SHA logic and only invoking bun publish when the registry check
indicates the version is not present.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 905e6000-e347-4126-8bd8-894e3b928992
📒 Files selected for processing (1)
.github/workflows/canary.yml
…node_modules Turbopack refuses to compile .ts/.tsx from node_modules. Instead of running Next.js with cwd: PACKAGE_ROOT (inside node_modules), the CLI now scaffolds a .chronicle/ directory in the user's project with copied source files and a content symlink. Next.js runs from .chronicle/ where Turbopack compiles normally. - Add scaffold utility that copies src/, source.config.ts, tsconfig.json and generates next.config.mjs - Update dev/build/start/serve commands to use scaffold cwd - Update init command to create package.json with deps, content/ subdirectory, and auto-install via detected package manager - Default content dir changed from cwd to ./content - Add .chronicle to .gitignore in init Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…manager via lockfiles - Move scaffoldDir call from dev/build/start/serve into init command - Commands now require .chronicle/ to exist (fail with helpful message) - Remove --content and -d flags from commands and init - Add resolveNextCli() using createRequire to avoid duplicate Next.js instances - Detect package manager via npm_config_user_agent then lockfile fallback - Update Dockerfile to use bun add + chronicle init flow - Add resolve.ts for PACKAGE_ROOT derivation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
packages/chronicle/src/cli/commands/serve.ts (1)
12-16: Consider extracting scaffold validation to a shared utility.This scaffold validation logic is duplicated in
build.ts(and likely other command files). Extracting it to a helper likeensureScaffold()in@/cli/utilswould reduce duplication and ensure consistent error messaging across commands.♻️ Example extraction
// In `@/cli/utils/scaffold.ts` export function ensureScaffold(): string { const scaffoldPath = path.join(process.cwd(), '.chronicle') if (!fs.existsSync(scaffoldPath)) { console.log(chalk.red('Error: .chronicle/ not found. Run'), chalk.cyan('chronicle init'), chalk.red('first.')) process.exit(1) } return scaffoldPath }Then in command files:
- const scaffoldPath = path.join(process.cwd(), '.chronicle') - if (!fs.existsSync(scaffoldPath)) { - console.log(chalk.red('Error: .chronicle/ not found. Run'), chalk.cyan('chronicle init'), chalk.red('first.')) - process.exit(1) - } + const scaffoldPath = ensureScaffold()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/chronicle/src/cli/commands/serve.ts` around lines 12 - 16, Extract the duplicated scaffold validation into a shared helper: create a new function ensureScaffold() in a utils module (e.g., `@/cli/utils/scaffold.ts`) that computes scaffoldPath = path.join(process.cwd(), '.chronicle'), checks fs.existsSync(scaffoldPath), logs the same error messages with chalk and calls process.exit(1) on failure, and returns scaffoldPath on success; then replace the inline logic in serve.ts (and the similar block in build.ts) with calls to ensureScaffold() to remove duplication and unify error messaging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/chronicle/src/cli/commands/init.ts`:
- Around line 72-79: The init command currently skips updating an existing
package.json (packageJsonPath) and only warns, causing required Chronicle fields
to be missing; modify the branch that handles an existing package.json to read
and parse the existing file, merge in the result of createPackageJson(dirName)
(only adding missing scripts, devDependencies, and other Chronicle-specific
fields without overwriting user values), then write the merged JSON back to
packageJsonPath before proceeding to scaffoldDir() and installation so
Chronicle's manifest entries are always present even when package.json already
exists.
- Around line 20-40: The createPackageJson function currently pins
'@raystack/chronicle' to 'latest' which breaks reproducibility; change
createPackageJson to read the running CLI/package version at runtime and use
that version string instead of 'latest' (e.g., derive from the package.json of
the running package or export the version from the CLI entry and consume it
here), update the dependency entry for '@raystack/chronicle' accordingly, and
also apply the same approach in packages/chronicle/src/cli/index.ts where the
CLI version is hardcoded so both uses come from the same package.json-derived
source.
In `@packages/chronicle/src/cli/commands/serve.ts`:
- Line 18: Wrap the call to resolveNextCli() in a try-catch and handle
MODULE_NOT_FOUND by logging a clear, user-friendly error (similar to the
.chronicle/ directory check) and exiting gracefully; specifically update
serve.ts (and mirror the same pattern in build.ts and start.ts) to catch errors
from resolveNextCli(), check err.code === 'MODULE_NOT_FOUND' and call the same
logger/message flow used for the .chronicle/ check before process.exit(1),
otherwise rethrow or log the unexpected error.
In `@packages/chronicle/src/cli/utils/resolve.ts`:
- Line 4: PACKAGE_ROOT currently resolves to packages/chronicle/src (one
directory too deep), causing scaffoldDir's COPY_FILES (which live at
packages/chronicle) to fail; update PACKAGE_ROOT in resolve.ts to climb three
levels from the current file (so it points at packages/chronicle) instead of
two. Locate the PACKAGE_ROOT constant and change the path.resolve call so it
goes up one more '..' (ensuring scaffoldDir and COPY_FILES reference the correct
package root).
In `@packages/chronicle/src/cli/utils/scaffold.ts`:
- Around line 96-99: The resolveNextCli function currently uses
createRequire(path.join(process.cwd(), 'package.json')) which resolves from the
project root and fails if the project doesn't list next; change it to resolve
next from Chronicle's package context by creating the require rooted at
Chronicle's package.json or the Chronicle module dirname (i.e., use
createRequire(path.join(__dirname, '..', 'package.json')) or
createRequire(require.resolve('@raystack/chronicle/package.json'))), then call
.resolve('next/dist/bin/next') so resolveNextCli reliably finds Next in
Chronicle's dependency scope.
---
Nitpick comments:
In `@packages/chronicle/src/cli/commands/serve.ts`:
- Around line 12-16: Extract the duplicated scaffold validation into a shared
helper: create a new function ensureScaffold() in a utils module (e.g.,
`@/cli/utils/scaffold.ts`) that computes scaffoldPath = path.join(process.cwd(),
'.chronicle'), checks fs.existsSync(scaffoldPath), logs the same error messages
with chalk and calls process.exit(1) on failure, and returns scaffoldPath on
success; then replace the inline logic in serve.ts (and the similar block in
build.ts) with calls to ensureScaffold() to remove duplication and unify error
messaging.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 201c9108-e194-4a8b-91c9-a81670215dab
📒 Files selected for processing (10)
Dockerfilepackages/chronicle/src/cli/commands/build.tspackages/chronicle/src/cli/commands/dev.tspackages/chronicle/src/cli/commands/init.tspackages/chronicle/src/cli/commands/serve.tspackages/chronicle/src/cli/commands/start.tspackages/chronicle/src/cli/utils/config.tspackages/chronicle/src/cli/utils/index.tspackages/chronicle/src/cli/utils/resolve.tspackages/chronicle/src/cli/utils/scaffold.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove extends @raystack/tools-config from tsconfig.json (standalone) - Move openapi-types from devDependencies to dependencies - Add -c/--content flag to init for custom content dir name - Skip sample index.mdx if content dir already has files - Update CLI, Docker, and Getting Started docs for new scaffold flow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass CHRONICLE_PROJECT_ROOT env var to Next.js child process so runtime config loader finds chronicle.yaml at the actual project root instead of .chronicle/ scaffold dir. Use tsconfig path alias for .source/server import to resolve correctly in scaffold context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tags Fumadocs returns search results with <mark> HTML tags for highlighting. Render them properly instead of showing raw HTML text. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use template literal for chalk error message in config.ts - Resolve Next.js CLI from Chronicle's PACKAGE_ROOT instead of cwd - Derive chronicle version from own package.json instead of hardcoding 'latest' - Add try-catch with user-friendly error for resolveNextCli in all commands - Add comment explaining PACKAGE_ROOT resolution path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
chronicle initcreates.chronicle/directory with copied source files, so Turbopack compiles TypeScript withoutnode_modulesrestrictions.chronicle/withCHRONICLE_PROJECT_ROOTenv var for config resolutionpackage.json, sets"type": "module", addsnode_modules/.next/.chronicleto.gitignore.source/serverimport: use tsconfig path alias@/.source/*instead of relative path<mark>tags viadangerouslySetInnerHTML@raystack/tools-config(unavailable to consumers)openapi-typesfrom devDependencies to dependenciesTest plan
npm packand install tarball in a fresh projectchronicle initcreates correct structurechronicle initon existing project merges missing scripts/depschronicle devstarts dev server, hot reload workschronicle build && chronicle startworks<mark>tags)chronicle.yamlconfig is read from project root🤖 Generated with Claude Code